'''继承'''
# 继承：实质从已经拥有的类衍生出来的，具备原来的行为，并且新的类还可以扩展自己的新功能
# 目的：延续旧类的功能，同时添加新功能
# 继承的说明：任何类型都直接或者间接的继承 object,之一切类的超类
# 类的属性__base__属性

# 基类(base class)：是指其他的父类或者基础，子类可以继承基类的属性和方法
# 超类(super class)：是更正式的术语，更强调层级关系，通常用于继承或比较复杂的继承结构
# 父类(father class)：更通俗的说法，常用于单继承
# 派生类(derived class)/子类(child class)：继承自其他的类


'''覆盖 override'''
# 子类继承了父类之后,在子类中定义和父类命名的方法,表示父类和子类都具备相同的功能
# 但是子类具有不同的实现,当调用时,调用的是子类覆盖之后的方法
# 如果子类中这个方法参数和父类不一样,算覆盖



'''super()'''
# 子类实例:__class__.__base__.方法(子类实例,参数)
# 基类名.方法名(子类实例,参数)
# super(B,b)，返回父类的一个实例
# 在子类的初始化函数中，需要显示的调用父类的初始化函数，这样才能妥善的处理子类继承自父类的那些属性的初始化功能。
# super()是个全局变量,不属于某一个类型,"super(B,b)"会返回父类的一个实例.
# 在函数中,可以直接使用"super().函数名(传参)"也能得到当前函数所在类的父类的实例就相当于


'''当发生覆盖时,子类的实例如何访问父类的方法'''
# class A():
#     def move(self,road):
#         print("A父类move",road)
#
# class B(A):
#     def move(self,water):
#         print("B父类move",water)
#
# b = B()
# # b.__class__.__bases__.move(b,"路")
# A.move(b,"路")# 调用了覆盖之前的,父类中的方法
# b.move("水")#调用的是子类的
# # A.move("马路")#move是对象级别的方法也就是实例方法，不能通过类来调用
# super(B,b).move("路")#调用了父类的方法



''''''
# class A():
#     def __init__(self,name):
#         print("A__init__")
#         self.name = name
#
# class B(A):
#     def __init__(self,age,name):
#         print("B__init__")
#         super().__init__(name)#调用父类的功能
#         self.age = age
#
# b = B(20,"张三")
# print(b.age)
# print(b.name)

class Bicycle():
    def __init__(self):
        pass
    def run(self,km):
        print("自行车行驶了",km,"公里")

class Ebicycle(Bicycle):
    def __init__(self,num):
        super().__init__()#继承父类
        self.num = num
    def run(self,km):
        temp = min(self.num*10,km)
        if temp >0 :
            print("用电一共走了",temp,"公里")
            self.num -= temp/10
        km -= temp
        if km > 0:
            super().run(km)#super()是内置函数
            print("当前还剩",self.num,"度电")
    #     if km <= self.num*10:
    #         print("自行车用电行驶了",km,"公里")
    #     else:
    #         super().run(km)
    #         km -= self.num*10
    #         print("自行车用电行驶了",self.num,"剩下的",km,"公里,用脚踩")
    def charge(self,num):
        self.num +=num
a = Bicycle()
a.run(100)



'''issubclass(class,class or tuple)判断某一个类是否是另一个类，或者元组中的某一个类的子类'''



'''封装 enclosure'''
# 封装的目的是隐藏累中的细节,调节者不需要关心细节
# 最终的目的让使用者尽可能的建设对实例变量的操作
# 在python中使用__开头的成员(资源),在外部是不可以访问,只能在内部访问

# class A():
#     def __init__(self):
#         self.__a = 1
#         self.b = 2
#
#     def __m1(self):
#         print("私有的m1函数执行","a:",self.__a,"b:",self.b)
#
#     def m2(self):
#         print("公开的函数m2")
#         self.__m1()
#
# a = A()
# # print(a.__a)#不能执行
# print(a.b)#2
# # a.__m1()#不能执行
# a.m2()



'''多态(状态)polymorphic'''
# 字面意思:"多种状态"
# 在基类/派生类中,不同的对象对于同一种行为,表现出不同的响应,
# 多态意味着不同的对象可以使用相同的接口,来调用不同的实现,最终实现了"方法相同,行为不同


# class Animal():
#     def move(self):
#         print("父亲Animal的移动")
#
# class Dog(Animal):
#     def move(self):
#         print("子类Dog使用腿移动")
#
# class Fish(Animal):
#     def move(self):
#         print("子类Fish使用尾巴移动")
#
# class Bird(Animal):
#     def move(self):
#         print("子类Bird使用翅膀或者腿移动")
#
# def my_move(a):#函数接收一个形参,不管其是什么类型,都调用相同的方法move
#     a.move()
#
# a = Animal()
# dog = Dog()
# fish = Fish()
# bird = Bird()
# my_move(a)
# my_move(dog)
# my_move(fish)
# my_move(bird)



'''面向对象的特点'''
# 继承:从基类中衍生出来的类,具有原类的所有的资源,实现代码的复用,结构清晰
# 封装:隐藏类的细节,相对安全
# 多态:多中状态,同一种行为有不同的响应,程序更加灵活和更高的扩展性
# 抽象:在抽象类的过程中,只关心那些和业务有关的属性.



'''多继承 multiple inheritance'''
# 一个子类继承自多个基类
# class 类名（类名1，类名2...）
#     pass
# 子类能继承所有父类的所有资源，但也可能造成冲突
# 当从若干个基类继承的资源重名产生了冲突时，默认情况下根据基类的先后顺序而定。
# 类中有一个属性，__mro__(method resolution order)，是一个有若干个类组成的元组，
# 代表这个类的对象查找属性时的寻找顺序。

# class A():
#     def m1(self):
#         print("A的m1函数")
#     def m(self):
#         print("A的m函数")
# class B():
#     def m2(self):
#         print("B的m2函数")
#     def m(self):
#         print("B的m函数")
# class C(B,A):
#     pass
#
# c = C()
# c.m1()#m1函数是从基类A中继承过来的
# c.m2()#m2函数是从基类B中继承过来的
# c.m()#当多继承A，B的时候



'''函数的重写'''
# 重写是定义在类里面的函数，让自定义的类的对象具备像内建函数一样，能够进行内建函数的操作,就是重写内建函数

# representation:表示
# __repr__():返回字符串,能够代表这个对象，通常 eval(repr(obj)) == obj,
# 这个函数的返回值更注重于为了让开发者更好的理解，更注重于准确。
# __str__：返回字符串，更注重于让用户能看得懂，可读性强。

# 说明:
# str(obj)优先调用__str__()如果没有这个__str_()，就调用__repr__()如果__repr__也没有，就调用超级父类的__repr_-，返回<0xxxxx >
# def__complex__complex(obj)
# def __int_.
# int(obj)
# def __float_float(obj)def -_bool_-
# bool(obj)

# class Student():
#     def __init__(self,name,age):
#         self.name = name
#         self.age = age
#
#     def __repr__(self):
#         return "Student(%s,%d)" % (self.name, self.age)
#     #
#     # def __str__(self):
#     #     return "姓名：%s,年龄: %d" % (self.name, self.age)
#
# s = Student("张三",18)
# print(str(s))
# print(repr(s))
